/*
 * FileAccess.java
 *
 * Copyright(c) 2010
 * Michael Kroez
 * kroez@studiorutton.de
 *
 * All rights reserved.
 *
 * $Id$
 * 
 */

package de.studiorutton.access;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.util.Date;

import de.studiorutton.access.FileAccessException.ErrorCode;

public class FileAccess {

	private FileLocation fileLocation;
	private final static int BUFF_SIZE = 65536;

	public FileAccess(FileLocation fileLocation) {
		this.fileLocation = fileLocation;
	}

	public FileLocation getFileLocation() {
		return fileLocation;
	}

	public void setFileLocation(FileLocation fileLocation) {
		this.fileLocation = fileLocation;
	}

	public FileProperties getFileProperties() throws FileAccessException {
		FileProperties fp = new FileProperties();

		File file = new File(fileLocation.createFilePath());
		fp.contentEncoding = fileLocation.getContentEncoding();
		if (!file.exists())
			return null;
		fp.lastModified = new Date(file.lastModified());

		fp.contentLength = file.length();
		fp.contentType = "*/*";

		return fp;
	}

	public boolean deleteFile() throws FileAccessException {
		File file = new File(fileLocation.createFilePath());
		if (file.exists()) {
			return file.delete();
		} else
			return false;
	}

	public OutputStream getOutputStream( boolean tmpFile ) throws FileAccessException {
		// inflater is the last in
		File localDir = new File(fileLocation.createFileDir());

		if (!localDir.exists())
			if (!localDir.mkdirs())
				throw new FileAccessException(
						FileAccessException.ErrorCode.ERROR_CANNOT_CREATE_DIR,
						fileLocation.createFileDir());

		File file = null;
		if ( tmpFile )
			file = new File(fileLocation.createTmpFilePath());
		else
			file = new File(fileLocation.createFilePath());
			
		try {
			file.createNewFile();
		} catch (IOException e) {
			throw new FileAccessException(ErrorCode.ERROR_CANNOT_CREATE_FILE,
					fileLocation.createFilePath());
		}

		FileOutputStream out = null;
		try {
			out = new FileOutputStream(file);
		} catch (FileNotFoundException e) {
			// A missing file is not allright - the check for writing something
			// is
			// already done.
		}
		if (out == null)
			throw new FileAccessException(ErrorCode.ERROR_WEIRD_WRITING,
					fileLocation.createFilePath());

		return out;
	}

	public InputStream getInputStream() throws FileAccessException {
		InputStream in;
		try {
			in = new FileInputStream(fileLocation.createFilePath());
		} catch (FileNotFoundException e) {
			throw new FileAccessException(ErrorCode.ERROR_CANNOT_READ,
					fileLocation.createFilePath());
		}
		return in;
	}

	public BufferedReader getReader() throws FileAccessException {
		if (fileLocation.charset == Tools.BINARY_CHARSET) {
			throw new FileAccessException(ErrorCode.ERROR_NO_CHARSET_FOR_READER);
		}
		InputStream in = getInputStream();
		InputStreamReader inReader = new InputStreamReader(in,
				Charset.forName(fileLocation.charset));
		BufferedReader bReader = new BufferedReader(inReader, BUFF_SIZE);
		return bReader;

	}

	public RandomAccessFile getRandomAccessFile() throws FileAccessException {
		RandomAccessFile raf;
		try {
			raf = new RandomAccessFile(fileLocation.createFilePath(), "r");
		} catch (Exception e) {
			throw new FileAccessException(ErrorCode.ERROR_CANNOT_READ,
					fileLocation.createFilePath());
		}
		return raf;
	}
	
	public boolean moveFromTmpToRealPath() throws FileAccessException {
		File file = new File( fileLocation.createTmpFilePath());
		File newFile = new File( fileLocation.createFilePath());
		boolean result = file.renameTo( newFile );
		return result;
	}

	public static boolean checkExistsAndReadable(FileLocation fileLocation)
			throws FileAccessException {
		File filePath = new File(fileLocation.createFilePath());
		if (filePath.exists() && filePath.canRead())
			return true;
		else
			throw new FileAccessException(ErrorCode.ERROR_CANNOT_READ,
					fileLocation.createFilePath());
	}

	public static boolean checkExternalStorageExists()
			throws FileAccessException {
		String ext = null;
		try {
			ext = FileLocation.getExternalStorage();
		} catch (IOException e) {
			throw new FileAccessException( ErrorCode.ERROR_CANNOT_FIND_EXTERNAL_STORAGE );
		}
		File extPath = new File( ext );
		if ( !extPath.exists() )
			throw new FileAccessException( ErrorCode.ERROR_CANNOT_FIND_EXTERNAL_STORAGE );
	
		if ( !extPath.canRead())
			throw new FileAccessException( ErrorCode.ERROR_CANNOT_READ_EXTERNAL_STORAGE );
		
		if ( !extPath.canWrite())
			throw new FileAccessException( ErrorCode.ERROR_CANNOT_WRITE_EXTERNAL_STORAGE );
		
		return true;
	}

}
